package com.hyperf.core.snowflake.worker;

import com.hyperf.core.exception.CustomException;
import com.hyperf.core.snowflake.WorkerRegister;
import com.hyperf.core.util.SnowflakeUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lizhaoyang
 */
@Slf4j
public abstract class AbstractWorkerRegister implements WorkerRegister {

    /**
     * 最多支持部署1024个节点
     */
    protected static final int MAX_WORKER_NUM = 1024;

    /**
     * 最大支持机器数
     */
    protected static final int MAX_WORKER_ID = 31;

    protected String applicationName;

    protected SnowflakeUtil snowflakeUtil;

    private int workerId;

    private int dataCenterId;

    public AbstractWorkerRegister(String applicationName) {
        this.applicationName = applicationName;
    }

    @Override
    public void registerWorker() {
        boolean registerStatus = false;
        // 尝试对 0-1023的值进行锁定
        for (int i = 0; i < MAX_WORKER_NUM; i++) {
            if (doRegister(i)) {
                registerStatus = true;
                workerId = i;
                break;
            }
        }

        if (!registerStatus) {
            throw new CustomException("Snowflake register workerId failed, [0, " + (MAX_WORKER_NUM - 1) + "] workerId be used");
        }

        if (workerId > MAX_WORKER_ID) {
            dataCenterId = workerId >> 5;
            workerId = workerId & 31;
        }

        if (log.isInfoEnabled()) {
            log.info("Snowflake worker registered success, workerId: {}, dataCenterId: {}", workerId, dataCenterId);
        }

        snowflakeUtil = new SnowflakeUtil(workerId, dataCenterId);
    }

    @Override
    public void deleteWorker() {
        doDelete(workerId);
    }

    /**
     * 注册机器ID
     *
     * @param workerId
     * @return
     */
    protected abstract boolean doRegister(int workerId);

    /**
     * 下线机器
     *
     * @param workerId
     * @return
     */
    protected abstract void doDelete(int workerId);

    @Override
    public SnowflakeUtil getSnowflakeUtil() {
        return snowflakeUtil;
    }
}
